-
Notifications
You must be signed in to change notification settings - Fork 1
RFC: Interoperable exceptions #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
bd7c3ce
to
8656647
Compare
8656647
to
56cccc9
Compare
Reporting here some comments on the preparation work to happen before this RFC. In terms of this RFC, one question is: how does one construct custom exceptions? The RFC describes how to pattern match them, but not how to construct and raise them. Here I'm assuming that there's a need to construct custom exceptions. If not, curious to learn why. Back to the runtime representation of exceptions, I think it's useful to break it up into parts, so that the issues addressed and the design space can be a bit clearer.
For 1, a standard-looking way would be to declare a ReScriptError subclass of Error, and use its constructor to set the name and payload (A and 42 for ReScript exception value A(42)). For 2, pattern matching would need to change so that JS exceptions are left untouched, not wrapped. It seems the simplest way would be to handle ReScript exception matching | A(n) => ... as simply checking instanceof ReScriptError (then extract name and payload). So no runtime would be used at all in pattern matching. For 3, there are many things one could do, and depend anyway on doing 1 and 2 first. |
There is already an open PR (rescript-lang/rescript#6979) and discussions for 1 and 2, and I thought we had already shared the same goals, but implicitly.
If we want to make the goals more clearer, I can write up another RFC for it with @DZakh However, the decision to make the payload count limit will also be an important consideration there as well. To use |
If a custom I will update the content to make it clearer. |
The problem with payload in a cause is that it might not be displayed in a terminal in some environments |
So it'll be a regression in terms of debugging. |
That's true if users are still on Node.js version 14 or Chrome 8x. Or custom renderers like React Native or vConsole. We need to investigate further, but I think they should be fine since they use the native |
When I was working on the task, my final thought was that it's better to use custom error classes. For example, this would turn into this: exception MyError(JsError.t) class MyError extends Error {
constructor(_0) {
super()
this._0 = _0
}
} And: exception MyError({
message: string,
err: JsError.t,
})
Console.log(MyError({message: "foo", err})) class MyError extends Error {
constructor(message, err) {
super()
this.message = message
this.err = err
}
}
console.log(new MyError("foo", err)) This way we'll be able to have:
|
It's actually the opposite. The Try your examples in Firefox browser. So the most widely supported form is class ReScriptError extends Error {
constructor(id, exn) {
super();
this.RES_EXN_ID = id;
// behave like a normal field even if no `Error.prototype.cause` support
this.cause = exn;
}
} So I expect the runtime representation of new ReScriptError(RES_EXN_ID, {
message: "foo",
err,
}); I also suggested using the However, I'm not particularly opposed to exporting exceptions as their own |
Providing a // in primitives
export class ReScriptError extends Error {
constructor(id, exn) {
super("ReScript exception: " + id);
this.RES_EXN_ID = id;
this.cause = exn;
}
}
// in the user module
import { ReScriptError } from "@rescript/runtime/es6/Primitive_extensions.js";
export class MyError extends ReScriptError {
constructor(exn) {
super("MyModule.ReScriptError", exn);
}
} |
A single class is definitely more manageable than one class per exception declaration. |
How important is the restriction to a single payload? |
Having a single class like |
Also, It might work in some environments, but this one I tested was like this one. And I really don't want to change the internal representation of the exn payload. |
So, I'd say the rfc can be split into two parts:
|
That's not true.
Any payload in Better formatter compatibility is why the standard did not choose another Error subclass. https://github.com/tc39/proposal-error-cause?tab=readme-ov-file#why-not-custom-subclasses-of-error |
I guess you're mainly testing on Chrome. Chromium DevTools seems to be the only one with the issue, and it needs to be fixed. |
Preview